#include "list.h"

mW_list * mW_list_create ()
{

	mW_list * list;
	
	list = (mW_list *) malloc(sizeof(mW_list));
	if (list == NULL)
		return NULL;
	
	list->size = 0;
	list->next_id = 0;
	list->first = NULL;
	list->last = NULL;
	list->iterator = NULL;
	
	return list;

}



mW_list_item * mW_list_create_item (mW_list * list, void * data)
{
	
	mW_list_item * item;
	
	item = (mW_list_item *) malloc(sizeof(mW_list_item));
	
	if (item == NULL)
		return NULL;
	
	item->id = 0;
	item->data = data;
	item->next_item = NULL;
	item->previous_item = NULL;
	
	return item;
}
	


int mW_list_delete (mW_list * list, int id)
{
	
	mW_list_item * list_item;
	
	if (list->size == 0)
		return 0;
	
	
	if (list->first->id == id)
	{

		free(list->first->data);
		list_item = list->first->next_item;
		free(list->first);
		
		if (list->last == list->first)
		{
			list->last = NULL;
			list->first = NULL;
		}
		else
		{
			list->first = list_item;
			list_item->previous_item = NULL;
		}

		list->size--;
		return 1;
	}
	
	
	list_item = list->first;
	
	while (list_item != NULL)
	{
		
		if (list_item->id == id)
		{
			
			if (list_item == list->last)
			{
				list->last = list_item->previous_item;
				list_item->previous_item->next_item = NULL;
			}
			else
			{
				list_item->previous_item->next_item = list_item->next_item;
				list_item->next_item->previous_item = list_item->previous_item;
			}
			
			free(list_item->data);
			free(list_item);
			
			list->size--;
			
			return 1;
			
		}
			
		list_item = list_item->next_item;
		
	}
	
	
	return 0;
	
}



int mW_list_delete_all (mW_list * list)
{
	
	mW_list_destroy_items(list->first);
	
	list->next_id = 0;
	list->size = 0;
	list->first = NULL;
	list->last = NULL;
	list->iterator = NULL;
	
	return 1;
	
}



int mW_list_delete_first (mW_list * list)
{
	
	if (list->last != NULL)
		return mW_list_delete(list, list->first->id);
	else
		return 0;
	
}



int mW_list_delete_last (mW_list * list)
{
	
	if (list->last != NULL)
		return mW_list_delete(list, list->last->id);
	else
		return 0;
	
}
		


int mW_list_destroy (mW_list * list)
{
	
	mW_list_destroy_items(list->first);
		
	free(list);
	
	return 1;
	
}



int mW_list_destroy_items (mW_list_item * list_item)
{
	if (list_item == NULL)
		return 0;
	
	if (list_item->next_item != NULL)
		mW_list_destroy_items(list_item->next_item);
	
	free(list_item->data);
	free(list_item);
	
	return 1;
	
}



void * mW_list_get_by_id (mW_list * list, int id)
{
	
	mW_list_item * list_item;
	
	list_item = list->first;
	
	while (list_item != NULL)
	{
		if (list_item->id == id)
			return list_item->data;
		list_item = list_item->next_item;
	}
	
	return NULL;
	
}



void * mW_list_get_first (mW_list * list)
{
	
	if (list->first == NULL)
		return NULL;
	else
		return list->first->data;
	
}



/*
 * Can also be used to search list to see if an element exists
 */
int mW_list_get_id (mW_list * list, void * data)
{
	
	mW_list_item * list_item;
	
	list_item = list->first;
	
	while (list_item != NULL)
	{
		if (list_item->data == data)
			return list_item->id;
		list_item = list_item->next_item;
	}
	
	return -1;
	
}



void * mW_list_get_last (mW_list * list)
{
	
	if (list->last == NULL)
		return NULL;
	else
		return list->last->data;
	
}



int mW_list_get_size (mW_list * list)
{
	
	return list->size;
	
}



int mW_list_insert (mW_list * list, void * data)
{
	
	if (list->first == NULL)
	{
		list->first = mW_list_create_item(list, data);
		if (list->first == NULL)
			mW_error("Error inserting list item\n");
		else
		{
			list->first->id = list->next_id++;
			list->size++;
		}
		list->last = list->first;
	}
	else
	{
		list->last->next_item = mW_list_create_item(list, data);
		if (list->last->next_item == NULL)
			mW_error("Error inserting list item\n");
		else
		{
			list->last->next_item->id = list->next_id++;
			list->size++;
			list->last->next_item->previous_item = list->last;
		}
			
		list->last = list->last->next_item;
	}
	
	return list->last->id;
	
}



int mW_list_insert_first (mW_list * list, void * data)
{
	
	mW_list_item * new_item;
	
	if (list->first == NULL)
	{
		list->first = mW_list_create_item(list, data);
		if (list->first == NULL)
			mW_error("Error inserting list item\n");
		else
		{
			list->first->id = list->next_id++;
			list->size++;
		}
		list->last = list->first;
	}
	else
	{
		
		new_item = mW_list_create_item(list, data);
		if (new_item == NULL)
			mW_error("Error inserting list item\n");
		new_item->next_item = list->first;
		list->first->previous_item = new_item;
		list->first = new_item;
		new_item->id = list->next_id++;
		list->size++;
		
	}
	
	return list->first->id;
	
}



void * mW_list_dont_iterate (mW_list * list)
{
	
	if (list->iterator == NULL)
		return NULL;
	else
		return list->iterator->data;
	
}



void * mW_list_iterate (mW_list * list, int direction)
{
	
	void * data;
	
	if (list->iterator == NULL)
		return NULL;
	
	data = list->iterator->data;
	
	if (direction == 1)
		list->iterator = list->iterator->next_item;
	else if (direction == -1)
		list->iterator = list->iterator->previous_item;
	
	return data;
	
}



/*
 * direction
 *   1 moves from 0 to n
 *   -1 moves from n to 0
 */
int mW_list_reset_iterator (mW_list * list, int direction)
{
	
	if (list->first == NULL)
		return 0;
	else if (direction == 1)
		list->iterator = list->first;
	else if (direction == -1)
		list->iterator = list->last;
	else
		return 0;
		
	return 1;
		
}
